#if !defined(MIN_HEAP)
#define MIN_HEAP

#include <iostream>
#include <netinet/in.h>
#include <time.h>

#define BUFF_SIZE 64

using std::exception;

class heap_timer;

/// @brief 用户数据
struct client_data
{
    sockaddr_in address;
    int sockfd;
    char buffer[BUFF_SIZE];
    heap_timer *timer;
};

/// @brief 定时器类
class heap_timer
{
public:
    heap_timer(time_t t_expire, client_data *t_user_data, void (*t_cb_func)(client_data *))
        : expire(t_expire), user_data(t_user_data), cb_func(t_cb_func) {}
    ~heap_timer() {}
    heap_timer(int delay) : expire(time(NULL) + delay) {}

public:
    /// @brief 生效时间
    time_t expire;
    /// @brief 用户数据
    client_data *user_data;
    /// @brief 回调函数
    void (*cb_func)(client_data *);
};

/// @brief 时间堆类
class time_heap
{
private:
    /// @brief 堆数组
    heap_timer **array;
    /// @brief 堆容量
    int capacity;
    /// @brief 当前包含元素数量
    int cur_size;

public:
    /// @brief 根据容量创建时间堆
    /// @param cap 容量
    time_heap(int cap) noexcept(0) : capacity(cap), cur_size(0)
    {
        array = new heap_timer *[capacity];
        if (!array)
            throw exception();
        for (int i = 0; i < capacity; i++)
            array[i] = NULL;
    }

    /// @brief 根据已有数组构建时间堆
    /// @param init_array 初始化数组
    /// @param size 元素数量
    /// @param capacity 容量
    time_heap(heap_timer **init_array, int size, int capacity) noexcept(0) : cur_size(size), capacity(capacity)
    {
        if (capacity < size)
            throw exception();
        array = new heap_timer *[capacity];
        if (!array)
            throw exception();
        for (int i = 0; i < capacity; i++)
            array[i] = NULL;
        if (size != 0)
        {
            for (int i = 0; i < size; i++)
                array[i] = init_array[i];
            for (int i = (cur_size - 1) / 2; i >= 0; --i)
                percolate_down(i);
        }
    }

    ~time_heap()
    {
        for (int i = 0; i < cur_size; i++)
            delete array[i];
        delete[] array;
    }

    void resize() noexcept(0);
    void percolate_down(int hole);

public:
    void tick();
    void adjust_timer(heap_timer *timer);

    heap_timer *top() const;
    bool empty() const;

    void add_timer(heap_timer *timer) noexcept(0);
    void del_timer(heap_timer *timer);
    void pop_timer();
};

#endif // MIN_HEAP
